<!-- 
  watch() 
    作用：监听响应式数据的变化，从而去做一些额外的业务逻辑
    语法：
      1.const stop = watch(source, handler, options)
        source: 要监听的数据源
          1. () => xxx
            watch(() => person.name)
          2. ref 数据
            const count = ref(1)
            watch(count)
          3. reactive 数据
            const person = reactive({})
            watch(person)
          4. 数组包含有上面三种类型
            watch([() => person.name, count, person])
        handler: 处理函数
          收到三个参数：
            1. newValue     新值
            2. oldValue     旧值
            3. onCleanup    清理函数
              该函数的触发时机是除了第一次，后续 handler 触发前触发
        options: 一些额外的配置
          deep: true      深度监听
          immediate: true 默认触发一次
          flush: 'pre'         触发事件
              'pre'   真实DOM更新之前触发。默认的
              'post'  真实DOM更新之后触发。
              'sync'  同步触发。不推荐使用有性能问题

        stop: watch() 的返回值
          1. 是个函数，调用该函数，会停止监听

  
  PS: 
    1. 直接监听 ref 数据，不要 .value 。否则不生效
    2. 直接监听 reactive 数据，会默认开启深度，不推荐这样写。推荐箭头函数具体去监听 reactive 中某个属性的方式
    3. flush 的 sync 慎用。

 -->

<template>
  <div>
    <h1>watch</h1>
    <p id="p">{{ person.name }}</p>
    <p>{{ person.age }}</p>
    <p>{{ count }}</p>
    <button @click="fn1">change person</button>
    <button @click="stop">stop</button>
  </div>
</template>

<script>
import { reactive, ref, watch } from 'vue'

export default {
  setup() {
    const count = ref(1)

    const person = reactive({
      name: '张三',
      age: 18
    })

    // 1. () => xxx
    //      直接监听 person.name
    watch(
      () => person.name,
      (newValue, oldValue) => {
        console.log('person.name new', newValue)
        console.log('person.name old', oldValue)
      }
    )

    // 2. ref
    watch(count, () => {
      console.log('count 修改了')
    })

    // 3. reactive
    //    如果直接监听一个 reactive，会默认开启深度监听
    watch(person, () => {
      console.log('person 修改了')
    })

    // 4. []
    const stop = watch([count, person], (newVal, oldValue) => {
      console.log('count 或 person 有修改', newVal)
    })

    function fn1() {
      person.age += 1
      // person.name += '~'
      // count.value++
    }

    // watch(
    //   () => person,
    //   (newValue, oldValue, onCleanup) => {
    //     // console.log('person.newValue', newValue)
    //     // console.log('person.oldValue', oldValue)
    //     // console.log('person.onCleanup', onCleanup)
    //     // const pEl = document.getElementById('p')
    //     // console.log(pEl.innerHTML)

    //     console.log('handler')
    //     const timer = setTimeout(() => {
    //       console.log('1')
    //     }, 1000)

    //     onCleanup(() => {
    //       console.log('onCleanup')
    //       // 清理的回调函数，
    //       //    该函数的触发时机是除了第一次，后续 handler 触发前触发
    //       clearTimeout(timer)
    //     })
    //   },
    //   {
    //     deep: true, // 深度监听
    //     // immediate: true, // 默认触发一次
    //     // flush: 'pre' // 真实DOM更新之前
    //     // flush: 'post' // 真实DOM更新之后
    //     flush: 'sync' // 同步更新
    //   }
    // )

    // function fn1() {
    //   // 当 flush 非 sync 时，下面的代码会让 watch 的 handler 回调只触发一次
    //   //          为 sync 时，下面的代码会让 watch 的 handler 回调触发两次（多次）。
    //   person.name += '~'
    //   person.age += 1
    // }

    return {
      person,
      fn1,
      count,
      stop
    }
  }
}
</script>
